#pragma once
#include <vector>
#include <exception>
#include <opencv2\core\core.hpp>
#include <QWidget>
#include <string>

class ProcessingGraph;

class Filter
{
public:
	class InputOutputIndexOutOfBoundsException : public std::exception
	{
	public:
		InputOutputIndexOutOfBoundsException(int streamNo, int max, Filter *first, Filter *second) : streamNo(streamNo), maxStreams(maxStreams), first(first), second(second) { }

		int streamNo;
		int maxStreams;
		Filter *first;
		Filter *second;
	};

	Filter(int inputs, int outputs);
	virtual ~Filter(void);

	void RunProcess();
	virtual void Process() = 0;
	virtual void ProcessInvalid();

	virtual QString GetFilterName();

	virtual QWidget *GetPropertiesWidget();
	virtual QWidget *GetOutputWidget();

	const int GetInputsCount() { return inputsCount; }
	const int GetOutputsCount() { return outputsCount; }

	bool IsReady();
	virtual void NextFrame();

	cv::Mat GetOutput(int index);

	void ConnectInput(int inputIndex, Filter &filter, int outputIndex);
	void ConnectInput(Filter &filter);
	Filter *GetInputFilter(int inputIndex);

	bool GetEndOfStream();

protected:
	cv::Mat *outputs;
	cv::Mat **inputs;

	bool *outputValid;
	bool **inputValid;

	bool endOfStream;

private:
	int inputsCount;
	int outputsCount;

	//Filter and filter's output index
	std::vector<std::pair<Filter*, int> > inputFilters;

	bool ready;
	friend class ProcessingGraph;
};
